/**
 * Copyright 厦门中软海晟信息技术有限公司 版权所有 违者必究 2019
 */
package com.opencvjava.lessons.imgproc;

import org.opencv.core.Core;
import org.opencv.core.Mat;
import org.opencv.core.MatOfFloat;
import org.opencv.core.MatOfInt;
import org.opencv.core.Range;
import org.opencv.imgproc.Imgproc;
import org.springframework.stereotype.Service;

import java.util.Arrays;
import java.util.List;

import static com.opencvjava.support.util.CvUtils.mat;
import static org.opencv.core.Core.normalize;
import static org.opencv.imgproc.Imgproc.calcHist;
import static org.opencv.imgproc.Imgproc.cvtColor;

/**
 * @author : sunzb(sunzb@hsit.com.cn)
 * @date: 2019/1/8
 */
@Service
public class L19_HistogramComparison {
    public void test() {
        Mat srcBase = mat("histogram", "Base_0.jpg");
        Mat srcTest1 = mat("histogram", "Test_1.jpg");
        Mat srcTest2 = mat("histogram", "Test_2.jpg");
        if (srcBase.empty() || srcTest1.empty() || srcTest2.empty()) {
            throw new RuntimeException("读取图片失败");
        }
        Mat hsvBase = new Mat(), hsvTest1 = new Mat(), hsvTest2 = new Mat();
        cvtColor(srcBase, hsvBase, Imgproc.COLOR_BGR2HSV);
        cvtColor(srcTest1, hsvTest1, Imgproc.COLOR_BGR2HSV);
        cvtColor(srcTest2, hsvTest2, Imgproc.COLOR_BGR2HSV);
        Mat hsvHalfDown = hsvBase.submat(new Range(hsvBase.rows() / 2, hsvBase.rows() - 1), new Range(0, hsvBase.cols() - 1));
        int hBins = 50, sBins = 60;
        int[] histSize = {hBins, sBins};
        // hue varies from 0 to 179, saturation from 0 to 255
        float[] ranges = {0, 180, 0, 256};
        // Use the 0-th and 1-st channels
        int[] channels = {0, 1};
        Mat histBase = new Mat(), histHalfDown = new Mat(), histTest1 = new Mat(), histTest2 = new Mat();
        List<Mat> hsvBaseList = Arrays.asList(hsvBase);
        calcHist(hsvBaseList, new MatOfInt(channels), new Mat(), histBase, new MatOfInt(histSize), new MatOfFloat(ranges), false);
        normalize(histBase, histBase, 0, 1, Core.NORM_MINMAX);
        List<Mat> hsvHalfDownList = Arrays.asList(hsvHalfDown);
        calcHist(hsvHalfDownList, new MatOfInt(channels), new Mat(), histHalfDown, new MatOfInt(histSize), new MatOfFloat(ranges), false);
        normalize(histHalfDown, histHalfDown, 0, 1, Core.NORM_MINMAX);
        List<Mat> hsvTest1List = Arrays.asList(hsvTest1);
        calcHist(hsvTest1List, new MatOfInt(channels), new Mat(), histTest1, new MatOfInt(histSize), new MatOfFloat(ranges), false);
        normalize(histTest1, histTest1, 0, 1, Core.NORM_MINMAX);
        List<Mat> hsvTest2List = Arrays.asList(hsvTest2);
        calcHist(hsvTest2List, new MatOfInt(channels), new Mat(), histTest2, new MatOfInt(histSize), new MatOfFloat(ranges), false);
        normalize(histTest2, histTest2, 0, 1, Core.NORM_MINMAX);
        // Correlation CV_COMP_CORREL  相关性 0~1 越高，接近1越相似
        // Chi-square CV_COMP_CHISQR 0~? 越低，接近0相似
        // Intersection CV_COMP_INTERSECT  交点 18.89..~0 越高，接近18.89越相似
        // Bhattacharyya CV_COMP_BHATTACHARYYA 0~1 越低，接近0越相似
        for (int compareMethod = 0; compareMethod < 4; compareMethod++) {
            double baseBase = Imgproc.compareHist(histBase, histBase, compareMethod);
            double baseHalf = Imgproc.compareHist(histBase, histHalfDown, compareMethod);
            double baseTest1 = Imgproc.compareHist(histBase, histTest1, compareMethod);
            double baseTest2 = Imgproc.compareHist(histBase, histTest2, compareMethod);
            System.out.println("Method " + compareMethod + " Perfect, Base-Half, Base-Test(1), Base-Test(2) : " + baseBase + " / " + baseHalf
                    + " / " + baseTest1 + " / " + baseTest2);
        }
    }
}
